package com.mobile.rail.alarm.ui;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.location.Address;
import android.location.Geocoder;
import android.location.GpsStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;

public class LocationActivity extends Activity {
	/** Called when the activity is first created. */

	GsmCellLocation location;
	int cellID, lac;
	private String TAG = "LocationActivity";
	public List<NeighboringCellInfo> neighbourList;
	public List<Integer> neighbourCellId;
	public List<Integer> neighbourCellIdSignal;
	public List<Double> neighbourCellIdLatitude;
	public List<Double> neighbourCellIdLongitude;
	public Map<Double, Double> neighbourLatLong;
	public List<Integer> neighbourCellType;

	public List<String> currentLocationAddress;
	public List<String> currentLocationData;
	private static final String GoogleCellID_URL = "http://www.google.com/glm/mmap";
	public double[] mLocation = new double[2];
	double[] resultGsmCellId = new double[2];

	private String gpslatitude, gpsLongitude;
	private static final int normalViewBtnID = Menu.FIRST;
	private static final int SdCardBtnID = Menu.FIRST + 1;

	private int group1Id = 0;

	private MyView myView;

	private static final int STATE_INITIAL = 0;
	private static final int STATE_RETRIEVING_CELL_ID = 1;
	private static final int STATE_RETRIEVING_NEIGHBOUR_DATA = 2;
	private static final int STATE_CONNECTING_SERVER = 3;
	private static final int STATE_CONNECTION_FAILED = 4;
	private static final int STATE_GETTING_GPS_COORDIANTES = 5;
	private static final int STATE_SHOW_RESULT = 6;
	private int state;
	private LocationManager locationManager;
	private GPSLocationListener locationListener;
	private long timerStartValue = 0;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		myView = new MyView(this);
		state = STATE_INITIAL;
		setContentView(myView);

		startDataProcessing();
	}

	private void startDataProcessing() {
		try {
			state = STATE_RETRIEVING_CELL_ID;
			myView.invalidate();
			getCellID();
			state = STATE_RETRIEVING_NEIGHBOUR_DATA;
			myView.invalidate();
			getAllNeighbourCellID();

			state = STATE_SHOW_RESULT;
			myView.invalidate();
		} catch (Exception e) {
			state = STATE_CONNECTION_FAILED;
			myView.invalidate();
			// TODO Auto-generated catch block
			Log.i(TAG, "Problem in CELL ID");
			e.printStackTrace();
		}
		getGPSData();
	}

	private void getCellID() throws Exception {
		TelephonyManager telephonymanager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		location = (GsmCellLocation) telephonymanager.getCellLocation();
		cellID = location.getCid();
		lac = location.getLac();

	}

	@SuppressWarnings("unchecked")
	private List getNeighbourInfo() {
		TelephonyManager telephonymanager = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
		neighbourList = telephonymanager.getNeighboringCellInfo();
		return neighbourList;
	}

	@SuppressWarnings("unchecked")
	private void getAllNeighbourCellID() throws Exception {
		List<NeighboringCellInfo> neigbourData = getNeighbourInfo();
		resultGsmCellId = getCurrentLocation_google_map_api(mLocation, cellID,
				lac);
		if (neigbourData != null) {
			neighbourCellId = new ArrayList<Integer>();
			neighbourCellIdSignal = new ArrayList<Integer>();
			neighbourCellIdLatitude = new ArrayList<Double>();
			neighbourCellIdLongitude = new ArrayList<Double>();
			neighbourCellType = new ArrayList<Integer>();
			state = STATE_CONNECTING_SERVER;
			for (int index = 0; index < neigbourData.size(); index++) {
				Log.i(TAG, "The NeighBourCell ID is"
						+ neigbourData.get(index).getCid());
				neighbourCellId.add(neigbourData.get(index).getCid());
				neighbourCellIdSignal.add(neigbourData.get(index).getRssi());
				neighbourCellType.add(neigbourData.get(index).getNetworkType());
				double[] neighbourGeoLocation = getCurrentLocation_google_map_api(
						mLocation, neigbourData.get(index).getCid(),
						neigbourData.get(index).getLac());
				neighbourCellIdLatitude.add(neighbourGeoLocation[0]);
				neighbourCellIdLongitude.add(neighbourGeoLocation[1]);
				Log.i(TAG, "The NeighBourCell ID  Signal Strength  is"
						+ neigbourData.get(index).getRssi());
				Log.i(TAG, "The NeighBourCell ID  Lat : "
						+ neighbourGeoLocation[0] + "The Long is"
						+ neighbourGeoLocation[1]);
			}
		}
	}

	private double[] getCurrentLocation_google_map_api(double[] location,
			int cellID, int lac) throws Exception {
		boolean result = true;
		String urlString = GoogleCellID_URL;

		// ---open a connection to Google Maps API---
		URL url;
		url = new URL(urlString);

		URLConnection conn = url.openConnection();
		HttpURLConnection httpConn = (HttpURLConnection) conn;
		httpConn.setRequestMethod("POST");
		httpConn.setDoOutput(true);
		httpConn.setDoInput(true);
		httpConn.setConnectTimeout(1000);
		httpConn.connect();

		// ---write some custom data to Google Maps API---
		OutputStream outputStream = httpConn.getOutputStream();
		WriteData(outputStream, cellID, lac);

		// ---get the response---
		InputStream inputStream = httpConn.getInputStream();
		DataInputStream dataInputStream = new DataInputStream(inputStream);

		// ---interpret the response obtained---
		Log.e("LocationUpdateService", "short=" + dataInputStream.readShort());
		Log.e("LocationUpdateService", "byte=" + dataInputStream.readByte());
		int code = dataInputStream.readInt();
		Log.e("LocationUpdateService", "code=" + code);
		if (code == 0) {
			double lat = (double) dataInputStream.readInt() / 1000000D;
			double lng = (double) dataInputStream.readInt() / 1000000D;
			dataInputStream.readInt();
			dataInputStream.readInt();
			dataInputStream.readUTF();
			dataInputStream.close();

			location[0] = lat;
			location[1] = lng;
			Log.i(TAG, "The Latitude IS" + lat + "Longitude is " + lng);
		} else {
			result = false;
		}
		httpConn.disconnect();
		return location;
	}

	private void WriteData(OutputStream out, int cellID, int lac)
			throws IOException {
		DataOutputStream dataOutputStream = new DataOutputStream(out);
		dataOutputStream.writeShort(21);
		dataOutputStream.writeLong(0);
		dataOutputStream.writeUTF("ja");
		dataOutputStream.writeUTF("Android");
		dataOutputStream.writeUTF("1.0");
		dataOutputStream.writeUTF("Web");
		dataOutputStream.writeByte(27);
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(3);
		dataOutputStream.writeUTF("");
		dataOutputStream.writeInt(cellID);
		dataOutputStream.writeInt(lac);
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(0);
		dataOutputStream.writeInt(0);
		dataOutputStream.flush();
		dataOutputStream.close();
	}

	private void sdCardAvailability() {
		final String status = Environment.getExternalStorageState();
		final File path = Environment.getExternalStorageDirectory();

		if (status.equals(Environment.MEDIA_MOUNTED)) {
			Log.i(TAG, "SD CARD MOUNTED");
			WriteToFile();
		} else {
			Toast toast = Toast.makeText(getBaseContext(),
					"SD CARDNOT FOUND!!!", Toast.LENGTH_LONG);
			toast.show();
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		//menu.add(group1Id, normalViewBtnID, group1Id, R.string.data_view);
		//menu.add(group1Id, SdCardBtnID, group1Id, R.string.Sd_cardwrite);
		return super.onCreateOptionsMenu(menu);
	}

	/**
	 * This is a method used for preparing the options menu.
	 */
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		super.onPrepareOptionsMenu(menu);
		return true;
	}

	/**
	 * This is a method used for handling event on the options menu.
	 */
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);
		Log.i("MenuActivity", "The ID ENTERED IS :" + item.getItemId());
		switch (item.getItemId()) {
		case normalViewBtnID:
			startDataProcessing();
			myView.invalidate();
			return true;
		case SdCardBtnID:
			sdCardAvailability();
			return true;
		default:
			Log.i("MenuActivity", "Other Items are  Clicked");
			return true;
		}
	}

	private boolean WriteToFile() {

		Calendar c = Calendar.getInstance();
		int seconds = c.get(Calendar.SECOND);
		int date = c.get(Calendar.DATE);
		int hour = c.get(Calendar.HOUR_OF_DAY);
		int minute = c.get(Calendar.MINUTE);
		String currentDateTimeString = String.valueOf(date) + "_"
				+ String.valueOf(hour) + "_" + String.valueOf(minute) + "_"
				+ String.valueOf(seconds);
		try {
			File root = Environment.getExternalStorageDirectory();
			if (root.canWrite()) {
				File txtfile = new File(root, "cellId" + currentDateTimeString
						+ ".txt");
				FileWriter txtwriter = new FileWriter(txtfile);
				BufferedWriter out = new BufferedWriter(txtwriter);
				out.write("GSM NETWORK DATA\r\n");
				out.write("-------------------- \r\n");
				out.write("CELL ID : " + cellID + "\r\n" + "Network LAC : "
						+ lac + "\r\n" + "GSM CELLID LAT :"
						+ resultGsmCellId[0] + ", " + resultGsmCellId[1]
						+ "\r\n");
				out.write("-------------------- \r\n");
				out.write("NEIGHBOUR NETWORK DATA \r\n");
				out.write("---------------------- \r\n");
				for (int index = 0; index < neighbourCellId.size(); index++) {
					out.write("NeighBour CELL ID INDEX : " + index + "\r\n"
							+ "CELL ID : " + neighbourCellId.get(index)
							+ "\r\n" + "SIGNAL : "
							+ neighbourCellIdSignal.get(index) + "\r\n"
							+ "Lat & Long  : "
							+ neighbourCellIdLatitude.get(index) + ","
							+ neighbourCellIdLongitude.get(index) + "\r\n"
							+ "CELL TYPE: " + neighbourCellType.get(index)
							+ "\r\n" + "\r\n");

				}
				out.write("-------------------- \r\n");
				out.write("CURRENT GPS DATA \r\n");
				out.write("---------------------- \r\n");
				if (gpslatitude != null) {
					out.write("Current GPS Location: " + gpslatitude + " , "
							+ gpsLongitude + " \r\n");
				} else {
					out.write("Current GPS Location: Not Available" + " \r\n");
				}
				out.write("-------------------- \r\n");
				out.write("CURRENT GPS DATA ADDREESS \r\n");
				out.write("---------------------- \r\n");
				if (currentLocationAddress != null) {
					for (int add = 0; add < currentLocationAddress.size(); add++) {
						out.write(currentLocationAddress.get(add));
					}
				}
				out.close();
				out = null;
				txtwriter.close();
				txtwriter = null;

			} else {
				Toast toast = Toast.makeText(getBaseContext(), "CanWrite : "
						+ root.getAbsolutePath() + " Error", Toast.LENGTH_LONG);
				toast.show();
				return false;
			}
		} catch (FileNotFoundException e) {
			e.getMessage();
			return false;
		} catch (IOException e) {
			e.getMessage();
			return false;
		}
		return true;
	}

	private void getGPSData() {
		Log.i("Pravin", "IN GPS DATA");
		locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationListener = new GPSLocationListener();
		// locationManager.addGpsStatusListener(locationListener);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0,
				0, locationListener);

		Log.i("Pravin", "IN GPS gpslatitude" + gpslatitude);
		if (gpslatitude == null) {

			Location currentLocation = null;

			/* last location with the network provider */
			if (currentLocation == null) {
				currentLocation = locationManager
						.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);

				if (currentLocation != null) {
					gpslatitude = String.valueOf(currentLocation.getLatitude());
					gpsLongitude = String.valueOf(currentLocation
							.getLongitude());
					Log.i("Pravin", "The gpsLatitude is " + gpslatitude);
					getReverseGeoCoding(currentLocation);

				}

			}

			/* last location with the network provider */
		}

	}

	private void getReverseGeoCoding(Location Loc) {
		Geocoder myLocation = new Geocoder(getApplicationContext(), Locale
				.getDefault());
		try {

			List<Address> myList = myLocation.getFromLocation(
					Loc.getLatitude(), Loc.getLongitude(), 1);
			currentLocationAddress = new ArrayList<String>();
			for (int index = 0; index < myList.size(); index++) {
				String Address = " ";
				for (int i = 0; i < myList.get(index).getMaxAddressLineIndex(); i++) {
					Address = Address + " "
							+ myList.get(index).getAddressLine(i) + " ";
				}
				currentLocationAddress.add(Address);
				Log.i(TAG, "The Location is "
						+ currentLocationAddress.get(index));
			}
		} catch (IOException e) {
			Log.i(TAG, "The Exception in Reverse Geo Coding : "
					);
			e.printStackTrace();
		}
	}

	public class MyView extends View {
		private Paint mPaint;
		private Paint mCellIdPaint;
		private Paint mneighbourIDPaint;
		private Paint mstatusPaint;

		private float LCD_WIDTH = 480;
		private float LCD_HEIGHT = 800;
		private float Y_STARTINGPOINT = 30;
		private float NEIGHBOUR_Y_STARTINGPOINT = 280;
		private float Y_OFFSET = 30;

		public MyView(Context c) {
			super(c);
			mPaint = new Paint();
			mPaint.setColor(Color.WHITE);
			mPaint.setStyle(Style.FILL);
			mPaint.setTextSize(15);
			mCellIdPaint = new Paint();
			mCellIdPaint.setColor(Color.RED);
			mCellIdPaint.setStyle(Style.FILL);
			mCellIdPaint.setTextSize(25);
			mneighbourIDPaint = new Paint();
			mneighbourIDPaint.setColor(Color.BLACK);
			mneighbourIDPaint.setStyle(Style.FILL);
			mneighbourIDPaint.setTextSize(25);
			mstatusPaint = new Paint();
			mstatusPaint.setColor(Color.RED);
			mstatusPaint.setStyle(Style.FILL);
			setFocusable(true);
		}

		@Override
		protected void onDraw(Canvas canvas) {

			switch (state) {
			case STATE_INITIAL:
				drawStatus(canvas, "Loading..");
				this.invalidate();
				break;
			case STATE_RETRIEVING_CELL_ID:
				drawStatus(canvas, "Retrieving Cell Id.. ");
				this.invalidate();
				break;
			case STATE_GETTING_GPS_COORDIANTES:
				break;
			case STATE_CONNECTING_SERVER:
				drawStatus(canvas, "Connecting server...");
				this.invalidate();
				break;
			case STATE_CONNECTION_FAILED:
				drawStatus(canvas, "Connection FAILED !!!!!!!!!!");
				this.invalidate();
				break;
			case STATE_SHOW_RESULT:
				drawFinalResult(canvas);
				this.invalidate();
				break;
			}

		}

		private void drawStatus(Canvas canvas, String display) {
			canvas.drawRect(0, 0, LCD_WIDTH, LCD_HEIGHT, mPaint);
			canvas.drawText(display, 10, Y_STARTINGPOINT, mstatusPaint);

		}

		private void drawFinalResult(Canvas canvas) {
			canvas.drawRect(0, 0, LCD_WIDTH, LCD_HEIGHT, mPaint);
			canvas.drawLine(0, 8, LCD_WIDTH, 8, mCellIdPaint);
			canvas.drawText("CURRENT CELL ID DATA", 10, Y_STARTINGPOINT,
					mCellIdPaint);
			canvas.drawLine(0, 35, LCD_WIDTH, 35, mCellIdPaint);
			canvas.drawText("CELL ID :" + String.valueOf(cellID), 10,
					Y_STARTINGPOINT + Y_OFFSET, mCellIdPaint);
			canvas.drawText("LAC ID :" + String.valueOf(lac), 10,
					Y_STARTINGPOINT + (2 * Y_OFFSET), mCellIdPaint);
			canvas.drawText("LATITUDE :" + String.valueOf(resultGsmCellId[0]),
					10, Y_STARTINGPOINT + (3 * Y_OFFSET), mCellIdPaint);
			canvas.drawText("LONGITUDE :" + String.valueOf(resultGsmCellId[1]),
					10, Y_STARTINGPOINT + (4 * Y_OFFSET), mCellIdPaint);
			canvas.drawLine(0, Y_STARTINGPOINT + (5 * Y_OFFSET), LCD_WIDTH,
					Y_STARTINGPOINT + (5 * Y_OFFSET), mCellIdPaint);
			canvas.drawText("NEIGHBOUR CELL ID DATA", 10, Y_STARTINGPOINT
					+ (6 * Y_OFFSET), mCellIdPaint);
			canvas.drawLine(0, Y_STARTINGPOINT + (7 * Y_OFFSET) - 10,
					LCD_WIDTH, Y_STARTINGPOINT + (7 * Y_OFFSET) - 10,
					mCellIdPaint);
			for (int index = 0; index < neighbourCellId.size(); index++) {
				canvas.drawText("NO: " + String.valueOf(index + 1)
						+ " CELL ID :"
						+ String.valueOf(neighbourCellId.get(index))
						+ " Signal Strength : "
						+ String.valueOf(neighbourCellIdSignal.get(index)), 10,
						NEIGHBOUR_Y_STARTINGPOINT + (index * Y_OFFSET),
						mneighbourIDPaint);
			}
			canvas
					.drawLine(0, NEIGHBOUR_Y_STARTINGPOINT
							+ (neighbourCellId.size() * Y_OFFSET), LCD_WIDTH,
							NEIGHBOUR_Y_STARTINGPOINT
									+ (neighbourCellId.size() * Y_OFFSET),
							mCellIdPaint);
			canvas.drawText("CURRENT LOCATION DATA", 10,
					NEIGHBOUR_Y_STARTINGPOINT
							+ ((neighbourCellId.size() + 1) * Y_OFFSET),
					mCellIdPaint);
			canvas.drawLine(0, NEIGHBOUR_Y_STARTINGPOINT
					+ ((neighbourCellId.size() + 2) * Y_OFFSET) - 10,
					LCD_WIDTH, NEIGHBOUR_Y_STARTINGPOINT
							+ ((neighbourCellId.size() + 2) * Y_OFFSET) - 10,
					mCellIdPaint);
			if (gpslatitude != null) {
				canvas.drawText("LAT&LONG: " + gpslatitude + " , "
						+ gpsLongitude, 10, NEIGHBOUR_Y_STARTINGPOINT
						+ ((neighbourCellId.size() + 3) * Y_OFFSET),
						mCellIdPaint);
				canvas.drawText("CURRENT ADDRESS :", 10,
						NEIGHBOUR_Y_STARTINGPOINT
								+ ((neighbourCellId.size() + 4) * Y_OFFSET),
						mCellIdPaint);
				if (currentLocationAddress != null) {
					for (int i = 0; i < currentLocationAddress.size(); i++) {
						canvas
								.drawText(
										currentLocationAddress.get(i),
										10,
										NEIGHBOUR_Y_STARTINGPOINT
												+ ((neighbourCellId.size() + 5) * Y_OFFSET),
										mCellIdPaint);
					}
				}
			} else {
				canvas.drawText("Current GPS Location: Not Available", 10,
						NEIGHBOUR_Y_STARTINGPOINT
								+ ((neighbourCellId.size() + 3) * Y_OFFSET),
						mCellIdPaint);
			}
		}

	}

	/**
	 * Starts the timer
	 */
	private void startTimer() {
		long curTime = System.currentTimeMillis();
		long totalTestTime = ((curTime - timerStartValue) / 1000);

		mTimerHandler.sendEmptyMessageDelayed(0, 1000);
	}

	/**
	 * Stops the timer
	 */
	private void stopTimer() {
		mTimerHandler.removeMessages(0);
	}

	/**
	 * Handler object. Used to simulate a timer.
	 */
	private final Handler mTimerHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			startTimer();
		}
	};

	/**
	 * Inner class. Acts as the listener to the location changes.
	 * 
	 * @author Accenture India
	 */
	private class GPSLocationListener implements LocationListener,
			GpsStatus.Listener {

		public void onProviderDisabled(String provider) {
			// TODO Auto-generated method stub
		}

		public void onProviderEnabled(String provider) {
			// TODO Auto-generated method stub
		}

		public void onStatusChanged(String provider, int status, Bundle extras) {
			// TODO Auto-generated method stub
		}

		public void onLocationChanged(Location Loc) {
			Log.i(TAG, "The Gps Location :" + Loc);
			if (Loc != null) {
				stopTimer();
				gpslatitude = String.valueOf(Loc.getLatitude());
				gpsLongitude = String.valueOf(Loc.getLongitude());
				Log.i(TAG, "The Gps Latitude :" + gpslatitude
						+ " The Longitude :" + gpsLongitude);
				getReverseGeoCoding(Loc);
				
			} else {

			}

		}

		public void onGpsStatusChanged(int arg0) {
			Log.i(TAG, "GPS STATUS CHANGED :" + arg0);
			// TODO Auto-generated method stub

		}
	}

}